home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1997 August / Walnut Creek CDROM.7z / VOL_400 / 453_01 / EXAMPLES / CATFISH / SETUPDLG.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-27  |  8.8 KB  |  311 lines

  1. //  setupdlg.cpp  -  setup dialog sample code  -  1.2
  2. //
  3. //  This is a part of the MetaKit library.
  4. //  Copyright (c) 1996 Meta Four Software.
  5. //  All rights reserved.
  6. /////////////////////////////////////////////////////////////////////////////
  7.  
  8. #include "stdafx.h"
  9. #include "catfish.h"
  10. #include "setupdlg.h"
  11. #include "pickdir.h"
  12.  
  13.     // the data structure used in the catalog, required for MetaKit version 1
  14. #define CAT_FORMAT  "dirs[parent:I,name:S,files[name:S,size:I,date:I]]"
  15.     
  16. #ifdef _DEBUG
  17. #undef THIS_FILE
  18. static char BASED_CODE THIS_FILE[] = __FILE__;
  19. #endif
  20.  
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CSetupDialog dialog
  23.  
  24. CSetupDialog::CSetupDialog(CWnd* pParent /*=NULL*/)
  25.     : CDialog(CSetupDialog::IDD, pParent),
  26.       m_exists (FALSE), m_timer (0), m_allowScan (FALSE)
  27. {
  28.     //{{AFX_DATA_INIT(CSetupDialog)
  29.     m_name = "";
  30.     //}}AFX_DATA_INIT
  31. }
  32.  
  33. void CSetupDialog::DoDataExchange(CDataExchange* pDX)
  34. {
  35.     CDialog::DoDataExchange(pDX);
  36.     //{{AFX_DATA_MAP(CSetupDialog)
  37.     DDX_Control(pDX, IDOK, m_okBtn);
  38.     DDX_Control(pDX, IDC_BROWSE_BTN, m_browseBtn);
  39.     DDX_Control(pDX, IDC_DEL_BTN, m_deleteBtn);
  40.     DDX_Control(pDX, IDC_ADD_BTN, m_addBtn);
  41.     DDX_Control(pDX, IDC_UPDATE_BTN, m_updateBtn);
  42.     DDX_Control(pDX, IDC_STATUS, m_status);
  43.     DDX_Control(pDX, IDC_ROOT, m_root);
  44.     DDX_Text(pDX, IDC_NAME, m_name);
  45.     //}}AFX_DATA_MAP
  46. }
  47.  
  48. BEGIN_MESSAGE_MAP(CSetupDialog, CDialog)
  49.     //{{AFX_MSG_MAP(CSetupDialog)
  50.     ON_BN_CLICKED(IDC_ADD_BTN, OnAddBtn)
  51.     ON_BN_CLICKED(IDC_UPDATE_BTN, OnUpdateBtn)
  52.     ON_BN_CLICKED(IDC_DEL_BTN, OnDelBtn)
  53.     ON_BN_CLICKED(IDC_BROWSE_BTN, OnBrowseBtn)
  54.     ON_EN_CHANGE(IDC_NAME, OnChangeName)
  55.     ON_EN_CHANGE(IDC_ROOT, OnChangeRoot)
  56.     ON_WM_TIMER()
  57.     ON_EN_KILLFOCUS(IDC_ROOT, OnKillfocusRoot)
  58.     //}}AFX_MSG_MAP
  59. END_MESSAGE_MAP()
  60.  
  61. /////////////////////////////////////////////////////////////////////////////
  62. // CSetupDialog message handlers
  63.  
  64.     // this member is called by the ScanDisk code during its (lengthy) scan
  65. bool CSetupDialog::UpdateStatus(const char* text)
  66. {
  67.     static DWORD lastTick = 0;
  68.     
  69.         // a null pointer forces immediate clear of the status text
  70.     if (!text)
  71.     {
  72.         lastTick = 0;
  73.         text = "";
  74.     }
  75.     
  76.         // only refresh the status message every quarter second
  77.     if (GetTickCount() > lastTick + 250)
  78.     {
  79.         lastTick = GetTickCount();
  80.         m_status.SetWindowText(text);   
  81.     }
  82.     
  83.     return cStatusHandler::UpdateStatus(text) && m_allowScan;
  84. }
  85.  
  86.     // the name has changed, update other fields (either now, or a little later)
  87.     // this delay is used to avoid excessive activity while a name is typed in
  88. void CSetupDialog::NameChange(BOOL delay)
  89. {
  90.     CString s;
  91.     if (m_name.IsEmpty())
  92.         s = "(please enter name of catalog)";
  93.     m_status.SetWindowText(s);
  94.  
  95.     m_exists = FALSE;
  96.     
  97.     if (delay)
  98.     {       // arm the timer (if there is a catalog name)
  99.         KillTimer(m_timer);
  100.         m_timer = m_name.IsEmpty() ? 0 :
  101.                     SetTimer(1, 500, 0); // timeout in 500 mS
  102.     }
  103.     else
  104.         InspectCatalog();
  105. }
  106.  
  107.     // scan through the directories, but be prepared to deal with premature abort
  108. void CSetupDialog::ScanDirectories()
  109. {
  110.     CString s;
  111.     m_root.GetWindowText(s);
  112.     
  113.         // prepare for a lengthy scan with a cancel option
  114.     AdjustButtons(TRUE);                        
  115.                             
  116.     m_okBtn.EnableWindow(FALSE);
  117.     m_browseBtn.SetWindowText("Abort");
  118.     SetDefID(IDC_BROWSE_BTN);
  119.  
  120.     m_allowScan = TRUE;
  121.                             
  122.         // build a catalog of the specified directory tree
  123.     c4_View dirs = fScanDirectories(s, this);
  124.                             
  125.         // restore normal situation
  126.     m_allowScan = TRUE;
  127.     m_okBtn.EnableWindow(TRUE);
  128.     m_browseBtn.SetWindowText("Browse");
  129.                             
  130.     m_status.SetWindowText("Saving catalog...");
  131.         // saving may take a litle time
  132.     HCURSOR oldCursor = SetCursor(LoadCursor(0, IDC_WAIT));
  133.     
  134.     if (dirs.GetSize() > 0)
  135.     {                        
  136.         s = m_name + FILE_TYPE;
  137.                                 
  138.             // clumsy, remove file to create smallest file
  139.         CFileStatus fs;
  140.         if (CFile::GetStatus(s, fs))
  141.             CFile::Remove(s);
  142.                                 
  143.             // this stores the catalog on file  
  144.         c4_Storage storage (s, CAT_FORMAT);
  145.         storage.Set("dirs", dirs);
  146.         storage.Commit();
  147.     }
  148.                             
  149.     SetCursor(oldCursor);
  150.     
  151.     InspectCatalog();
  152. }     
  153.  
  154.     // go see if the catalog exists and get its file date and root path
  155. void CSetupDialog::InspectCatalog()
  156. {
  157.     UpdateData();
  158.                             
  159.     CString s = GetCatalogDate(m_name);
  160.     if (!s.IsEmpty())
  161.         s = "Last change:  " + s;
  162.  
  163.     UpdateData(FALSE); // adjusts the name
  164.                                                             
  165.     m_status.SetWindowText(s);
  166.     m_exists = !s.IsEmpty();
  167.                                 
  168.     if (m_exists)
  169.     {
  170.             // load the root path name from the catalog
  171.             // this is quick, due to on-demand loading
  172.         c4_Storage storage (m_name + FILE_TYPE);
  173.         c4_View dirs = storage.Get("dirs");
  174.         m_origRoot = pName (dirs[0]);
  175.         m_root.SetWindowText(m_origRoot);
  176.     }
  177. }
  178.  
  179.     // adjust the button dimming and titles to reflect the current situation
  180. void CSetupDialog::AdjustButtons(BOOL inScan_)
  181. {
  182.     CString s;
  183.     m_root.GetWindowText(s);
  184.     BOOL valid = !s.IsEmpty() && !inScan_;
  185.     
  186.         // don't enable buttons while the timer is running  
  187.     m_addBtn.EnableWindow(valid && !m_exists && !m_timer && !m_name.IsEmpty());
  188.     
  189.     ASSERT(!(m_exists && m_timer)); // if it exists, timer cannot be running
  190.     m_updateBtn.EnableWindow(valid && m_exists);
  191.     m_deleteBtn.EnableWindow(valid && m_exists);
  192.     
  193.         // The default button is "OK" for existing files
  194.         // If the root has been set for a new file, the default is "Add"
  195.         // For new files, or if the root is different, the default is "Browse"
  196.         // Never make "Change" the default, since that is a dangerous change
  197.     SetDefID(valid &&  m_exists && s == m_origRoot ? IDOK :
  198.              valid && !m_exists && !m_timer        ? IDC_ADD_BTN : 
  199.                                                      IDC_BROWSE_BTN);
  200.     
  201.     if (!GetFocus())
  202.         m_okBtn.SetFocus();
  203. }
  204.                             
  205.         // called shortly after a change to the name or root edit control       
  206. void CSetupDialog::OnTimer(UINT nIDEvent)
  207. {
  208.     KillTimer(m_timer);
  209.     m_timer = 0;
  210.     
  211.     InspectCatalog();
  212.     OnChangeRoot();
  213.     
  214.     CDialog::OnTimer(nIDEvent);
  215. }
  216.             
  217. BOOL CSetupDialog::OnInitDialog()
  218. {
  219.     CenterWindow();
  220.     CDialog::OnInitDialog();
  221.     
  222.     m_nameEditCtrl.SubclassDlgItem(IDC_NAME, this);
  223.     
  224.     NameChange(FALSE);
  225.     AdjustButtons();
  226.     
  227.     return TRUE;  // return TRUE  unless you set the focus to a control
  228. }
  229.  
  230. void CSetupDialog::OnAddBtn()
  231. {
  232.     OnKillfocusRoot();
  233.     ScanDirectories();
  234.     AdjustButtons();
  235. }
  236.  
  237. void CSetupDialog::OnUpdateBtn()
  238. {
  239.     OnKillfocusRoot();
  240.     ScanDirectories();
  241.     AdjustButtons();
  242. }
  243.  
  244. void CSetupDialog::OnDelBtn()
  245. {
  246.     if (AfxMessageBox("Do you want to permanently delete "
  247.                         "the catalog named '" + m_name + "' ?",
  248.                         MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2) == IDYES)
  249.     {
  250.         CFile::Remove(m_name + FILE_TYPE);
  251.  
  252.         NameChange(TRUE);
  253.         AdjustButtons();
  254.     }
  255. }
  256.  
  257. void CSetupDialog::OnBrowseBtn()
  258. {
  259.     if (m_allowScan)
  260.     {
  261.         m_allowScan = FALSE;
  262.         return;
  263.     }
  264.     
  265.     CString dir = PickDirectory(this);
  266.     if (!dir.IsEmpty())
  267.         m_root.SetWindowText(dir); // triggers OnChangeRoot()
  268. }
  269.  
  270. void CSetupDialog::OnChangeName()
  271. {
  272.     VERIFY(UpdateData());
  273.  
  274.     NameChange(TRUE);
  275.     AdjustButtons();
  276. }
  277.  
  278. void CSetupDialog::OnChangeRoot()
  279. {
  280.     CString s;
  281.     m_root.GetWindowText(s);
  282.                             
  283.     BOOL changed = m_exists && s != m_origRoot;
  284.     m_updateBtn.SetWindowText(changed ? "&Change" : "&Update");
  285.     
  286.     AdjustButtons();
  287. }
  288.  
  289. void CSetupDialog::OnKillfocusRoot()
  290. {
  291.     CString s;
  292.     m_root.GetWindowText(s);
  293.     
  294.     if (!s.IsEmpty())
  295.     {
  296.         s.MakeUpper();
  297.         if (s.Right(1) != "\\")
  298.             s += "\\"; // avoid handing "C:" to _fullpath
  299.  
  300.         char buf [_MAX_PATH];
  301.         if (_fullpath(buf, s + "nul", sizeof buf))
  302.         {
  303.             s = buf;
  304.         
  305.             CFileStatus fs;
  306.             if (CFile::GetStatus(s, fs))
  307.                 m_root.SetWindowText(s.Left(s.GetLength() - 4));
  308.         }
  309.     }
  310. }
  311.